package com.maodou.android.data.remote

import com.maodou.android.data.model.AccountCheckResp
import com.maodou.android.data.model.ProxyCheckResp
import com.maodou.android.data.model.TwofaCodeResp
import com.maodou.core.datastore.db.AccountStore
import com.maodou.core.network.NetworkResult
import com.maodou.core.network.flowApiEnvelopeCall
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
import android.content.Context
import android.os.Environment
import com.maodou.android.data.model.AccountAuthInfo
import com.maodou.core.datastore.db.table.AccountEntry
import com.maodou.core.network.ApiEnvelope
import com.maodou.core.utils.Logger
import dagger.hilt.android.qualifiers.ApplicationContext
import java.io.File
import java.io.IOException
import com.maodou.android.utils.FileUtils
import com.maodou.android.utils.FileUtils.getAuthFileFile
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
 * @Author Xing
 * @CreateTime 2025年09月24日
 * @Description TODO
 */
class AccountRepository @Inject constructor(
    private val service: ApiService,
    private val accountStore: AccountStore,
    @ApplicationContext private val appContext: Context,
) {

    fun getTwoFaCode(key: String): Flow<NetworkResult<TwofaCodeResp>> =
        flowApiEnvelopeCall {
            service.getTwoFaCode(key)
        }

    fun onAccountCheck(accountID: String,platform:String): Flow<NetworkResult<AccountCheckResp>> =
        flowApiEnvelopeCall {
            val params: Map<String, String> = mapOf(
                "uid" to accountID,
                "platform" to platform
            )
            val result = service.onAccountCheck(params)
            //根据检查结果更新本地数据库
            val accountInfo = accountStore.findByAccountId(accountID)
            if(accountInfo != null){
                accountInfo.lastCheck = System.currentTimeMillis()
                accountInfo.online = if(result.data?.status == "ACTIVE") 2 else if(result.data?.status == "BAN") 3 else 1
                accountStore.upsert(accountInfo)
            }
            result
        }

    fun onProxyCheck(channel: String,protocol:String,host:String,port:String,username:String,password:String): Flow<NetworkResult<ProxyCheckResp>> =
        flowApiEnvelopeCall {
            val params: Map<String, String> = mapOf(
                "channel" to channel,
                "protocol" to protocol,
                "host" to host,
                "port" to port,
                "username" to username,
                "password" to password,
            )
            service.onProxyCheck(params)
        }


    /**
     * 获取快速登录  认证文件
     *
     * @param accountEntry 本地账号信息
     * @return 解压保存后的文件
     * @throws IOException 如果保存失败
     */
    fun getAccountAuthInfo(accountEntry: AccountEntry): Flow<NetworkResult<File>> =
        flowApiEnvelopeCall {

            val targetFile = File(appContext.filesDir, "auth/${accountEntry.accountID}.tar.gz")
            var unpackFile:File? = null

            //已经存在相关文件 不在二次下载 直接返回结果
            if (targetFile.exists() && targetFile.length() > 0) {
                unpackFile = getAuthFileFile(appContext, accountEntry.accountID, targetFile)
                return@flowApiEnvelopeCall ApiEnvelope(success = true, code = "SUCCESS", message = "操作成功", data = unpackFile)
            }

            //获取认证文件Base64信息
            val result = service.getAccountAuthInfo("${accountEntry.authCode}")

            if(result.success == true) {
                result.data?.let { authInfo ->
                    try {
                        val savedFile = saveAuthInfoToFile(authInfo)
                        unpackFile = getAuthFileFile(appContext, accountEntry.accountID, savedFile)
                    } catch (e: Exception) {
                        Logger.e("保存认证文件失败: ${e.message}", e)
                    }
                }
            }

            ApiEnvelope(success = result.success, code = result.code, message = result.message, data = unpackFile)
        }

    /**
     * 保存认证信息到文件
     * 将Base64编码的GZIP数据解码并保存为ZIP文件
     * 
     * @param authInfo 认证信息对象
     * @return 保存后的文件
     * @throws IOException 如果保存失败
     */
    @Throws(IOException::class)
    private suspend fun saveAuthInfoToFile(authInfo: AccountAuthInfo): File = withContext(Dispatchers.IO) {
        val uid = authInfo.uid ?: throw IOException("UID不能为空")
        val content = authInfo.content ?: throw IOException("Content不能为空")

        // APP私有目录下的auth文件夹
        val authDir = File(appContext.filesDir, "auth")
        
        // 解码Base64并解压GZIP，保存文件
        FileUtils.decodeBase64GzipToFile(content, uid, authDir)
    }

}